//
//  KismetController.m
//  kismet-frontend
//
//  Created by L. Preston Sego III on 7/18/09.
//  Copyright 2009 Precognition Inc.. All rights reserved.
//

#import "KismetController.h"
#import "Constants.h"

@implementation KismetController


-(id)init
{
    if(self = [super init])
    {
        server_host = @"127.0.0.1";
        server_port = 2501;
    }
    return self;
}

- (void)connectAndSetupServer
{
    NSLog([NSString stringWithFormat:@"Attempting to set up server %@ on port %d", server_host, (int)server_port]);
    
    // connect to server    
    if (![server_host isEqualToString:@""]) 
    {
        NSURL *website = [NSURL URLWithString:server_host];
        if (!website) 
        {
            NSLog(@"%@ is not a valid host address");
            return;
        }
        
        NSHost *host = [NSHost hostWithName:server_host];
        [NSStream getStreamsToHost:host 
                              port:server_port 
                       inputStream:&iStream 
                      outputStream:&oStream];
        
        NSLog(@"Connected to server, setting up streams...");
       [self openStreams];
        
        NSLog(@"Streams are open");
        
        [self killTime];
        
        //NSLog([NSString stringWithFormat:@"Response from Server: %@", [self sendCommandToServer:@"!0 CAPABILITY BSSID\n"]]);
    }
    
    
}


- (void)openStreams
{
    [iStream retain];
    [oStream retain];
    [iStream setDelegate:self];
    [oStream setDelegate:self];
    [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
                       forMode:NSDefaultRunLoopMode];
    [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
                       forMode:NSDefaultRunLoopMode];
    [iStream open];
    [oStream open];
}

- (void)closeStreams
{
    [iStream close];
    [oStream close];
    [iStream removeFromRunLoop:[NSRunLoop currentRunLoop] 
                       forMode:NSDefaultRunLoopMode];
    [oStream removeFromRunLoop:[NSRunLoop currentRunLoop] 
                       forMode:NSDefaultRunLoopMode];
    [iStream setDelegate:nil];
    [oStream setDelegate:nil];
    [iStream release];
    [oStream release];
    iStream = nil;
    oStream = nil;
}


- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent
{
    NSInputStream * istream;
    switch(streamEvent) 
    {
        case NSStreamEventHasBytesAvailable:;
            uint8_t oneByte;
            int actuallyRead = 0;
            istream = (NSInputStream *)aStream;
            if (!dataBuffer) 
            {
                dataBuffer = [[NSMutableData alloc] initWithCapacity:2048];
            }
            actuallyRead = [istream read:&oneByte maxLength:1];
            if (actuallyRead == 1) 
            {
                [dataBuffer appendBytes:&oneByte length:1];
            }
            if (oneByte == '\n') 
            {
                // We've got the carriage return at the end of the echo. Let's set the string.
                NSString * string = [[NSString alloc] initWithData:dataBuffer encoding:NSUTF8StringEncoding];
                [self processData:[string copy]];
                //responseString = [string copy];
                [string release];
                [dataBuffer release];
                dataBuffer = nil;
            }
            
            break;
        case NSStreamEventEndEncountered:;
            [self closeStreams];
            break;
        case NSStreamEventHasSpaceAvailable:
        case NSStreamEventErrorOccurred:
        case NSStreamEventOpenCompleted:
        case NSStreamEventNone:
        default:
            break;
    }
    
}

-(void)processData:(NSString *)stringOfData
{
    responseString = [NSString stringWithFormat:@"%@%@", responseString, stringOfData];
}


-(NSString *)sendCommandToServer:(NSString *)command
{    
    NSString *temp;
    command = [NSString stringWithFormat:@"!0 %@", command]; //
    
    if (oStream) // make sure oStream is pointing somewhere
    {
        NSData * dataToSend = [command dataUsingEncoding:NSUTF8StringEncoding];
        int remainingToWrite = [dataToSend length];
        void * marker = (void *)[dataToSend bytes];
        while (0 < remainingToWrite) 
        {
            int actuallyWritten = 0;
            actuallyWritten = [oStream write:marker maxLength:remainingToWrite];
            remainingToWrite -= actuallyWritten;
            marker += actuallyWritten;
        }
    }
    
    temp = [responseString copy];
    responseString = @"";
    
    return temp;
}

#pragma mark GUI Communication

-(void)awakeFromNib
{    
    [window makeKeyAndOrderFront:nil];
    [window center];
}


- (IBAction)go:(id)sender
{    
    NSString * stringToSend = [NSString stringWithFormat:@"%@\n", [sender stringValue]];
    [response setTitleWithMnemonic:[self sendCommandToServer:stringToSend]];
    
    [commandEntry selectText:sender];
    [response updateTrackingAreas];
}

#pragma mark basic server commands

- (void)killServer
{
    [self sendCommandToServer:@"shutdown"];
}

- (NSString *)enable:(NSString *)protocol
{
    return [self enable:protocol withOptionsSeparatedByCommas:@""];
}

- (NSString *)enable:(NSString *)protocol withOptionsSeparatedByCommas:(NSString *)options
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"enable %@ %@", protocol, options]];
}

- (NSString *)disable:(NSString *)protocol
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"remove %@", protocol]];
}

- (NSString *)addSource:(NSString *)uuid
{
    return [self addSource:uuid withOptions:@""];
}

- (NSString *)addSource:(NSString *)uuid withOptions:(NSString *)options
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"addSource %@ %@", uuid, options]];
}

- (NSString *)deleteSource:(NSString *)uuid
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"delSource %@", uuid]];
}

- (NSString *)channelHop:(NSString *)uuid
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"chanHop %@", uuid]];
}

- (NSString *)channelLock:(NSString *)uuid forChannel:(NSString *)channels
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"chanLock %@ %@", uuid, channels]]; 
}

- (NSString *)channelSequence:(NSString *)uuid forCommaSeparatedListOfChannels:(NSString *)listOfChannels
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"chanSeq %@ %@", uuid, listOfChannels]];
}

- (NSString *)listWepKeys
{
    return [self sendCommandToServer:@"listWepKeys"];
}

- (NSString *)addWepKey:(NSString *)bssid forKeyInHex:(NSString *)key
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"addWepKey %@ %@", bssid, key]];
}

- (NSString *)deleteWepKey:(NSString *)bssid
{
    return [self sendCommandToServer:[NSString stringWithFormat:@"delWepKey %@", bssid]];
}


- (void)killTime
{
     [self sendCommandToServer:@"remove time\n"];
}

- (void)startSendingNetworkInfo
{
    [self enable:SSID_SCAN_STRING];
    [self enable:BSSID_SCAN_STRING];
}

- (void)stopSendingNetworkInfo
{
    [self disable:@"SSID"];
    [self disable:@"BSSID"]; 
}

@end